package com.zhiren.settlement;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.script.ScriptException;

import com.zhiren.settlement.SettlementOp;

import com.zhiren.common.CustomMaths;
import com.zhiren.common.ListTools;
import com.zhiren.common.MapUtils;
import com.zhiren.formular.Calculator;

import java.util.Map.Entry;

public class Settlement {
	public static final String SettlementType001 = "001"; 	//结算类型代码001为先加权后汇总
	public static final String SettlementType002 = "002"; 	//结算类型代码002为先汇总后加权
	
	public static final String ResultType_Weighted_Sum ="WeightedSum";	//先计算各项单价的加权平均然后加权平均单价和为总单价
	public static final String ResultType_Sum_Weighted ="SumWeighted";	//先计算各项单价的和为各批总单价然后计算加权平均单价
	
	static Map<String,String> propsmap;		//结算属性设置
	static Map<String,String> roundingmap;	//小数位修约设置
	
	public Map<String,String> roundModemap4contract = new HashMap<String,String>();
	public Map<String,String> roundModemap4System;
	
	public Settlement() throws UnsupportedEncodingException, IOException{
//		读取配置文件
		InputStream is = SettlementOp.class
				.getResourceAsStream("definition.properties");
		if (is != null) {
			
			Properties props = new Properties();
			props.load(new InputStreamReader(is,"UTF-8"));
			
			propsmap = new HashMap<String,String>();
		    Iterator<Entry<Object, Object>> itr = props.entrySet().iterator();
		    while (itr.hasNext()) {
		      Entry<Object, Object> e = (Entry<Object, Object>) itr.next();
//		      System.out.println(e);
		      propsmap.put(e.getKey().toString(), e.getValue().toString());
		    }
			is.close();
		}
//		读取小数位配置文件
		is = SettlementOp.class
				.getResourceAsStream("rounding-default.properties");
		if (is != null) {
			
			Properties props = new Properties();
			props.load(new InputStreamReader(is,"UTF-8"));
			
			roundingmap = new HashMap<String,String>();
		    Iterator<Entry<Object, Object>> itr = props.entrySet().iterator();
		    while (itr.hasNext()) {
		      Entry<Object, Object> e = (Entry<Object, Object>) itr.next();
//		      System.out.println(e);
		      roundingmap.put(e.getKey().toString(), e.getValue().toString());
		    }
			is.close();
		}
//		读取系统对应指标的修约方法文件
		is = SettlementOp.class
				.getResourceAsStream("roundmode-default.properties");
		if (is != null) {
			
			Properties props = new Properties();
			props.load(new InputStreamReader(is,"UTF-8"));
			roundModemap4System = new HashMap<String,String>();
		    Iterator<Entry<Object, Object>> itr = props.entrySet().iterator();
		    while (itr.hasNext()) {
		      Entry<Object, Object> e = (Entry<Object, Object>) itr.next();
//		      System.out.println(e);
		      roundModemap4System.put(e.getKey().toString(), e.getValue().toString());
		    }
			is.close();
		}
	}
	
	/**
	 * 将指标数据写入源list
	 * @param sourcesList	源list
	 * @param addMap		数据
	 * @param strKeySuffix		数据key后缀 可为null
	 */
	private void appendListMap(List<Map<String,String>> sourcesList, Map<String,String> addMap, String strKeySuffix){
		Iterator<Entry<String, String>> mapIterator = addMap.entrySet().iterator();
		while(mapIterator.hasNext()){
			Entry<String, String> e = (Entry<String, String>)mapIterator.next();
			String strKey = e.getKey() + (strKeySuffix==null?"":strKeySuffix);
			String strValue = e.getValue();
			for(int i=0; i< sourcesList.size(); i++){
				Map<String,String> batchMap = sourcesList.get(i);
				batchMap.put(strKey, strValue);
			}
		}
	}
	
	/**
	 * 将第二个map中的内容写入第一个map 重复的key不覆盖
	 * @param sourcesMap
	 * @param addMap
	 */
	private void appendMap(Map<String,String> sourcesMap, Map<String,String> addMap){
		Iterator<Entry<String, String>> addIterator = addMap.entrySet().iterator();
		while(addIterator.hasNext()){
			Entry<String, String> e = (Entry<String, String>)addIterator.next();
			String strKey = e.getKey();
			String strValue = e.getValue();
			if(!sourcesMap.containsKey(strKey)){
				sourcesMap.put(strKey, strValue);
			}
		}
	}
	
	/**
	 * 普通结算操作
	 * @param sources
	 * @param balanceTemplate
	 * @return
	 * @throws Exception
	 */
	public SettlementResult calculation(List<Map<String,String>> sourcesList,SettlementTemplate balanceTemplate) throws Exception{
//		参数验证
		if(sourcesList == null || sourcesList.isEmpty()){
			throw new Exception("结算数据为空");
		}
		if(balanceTemplate == null){
			throw new Exception("结算方案模板为空");
		}
//		对结算分组条件排序，因为系统默认包含加权及单批次的分组处理，需要加权的批次在最先处理。
		List<Map<String,String>> groupList  = balanceTemplate.getGroupList();
		List<Map<String,String>> groupListAsc = new ArrayList<Map<String,String>>();
		for(int i=0; i< groupList.size(); i++){
			Map<String,String> groupMap = groupList.get(i);
			String strMode = (String)groupMap.get(SettlementOp.TMP_GROUP_MAP_KEY_MODE);
			if(SettlementOp.PRICE_MODE_WEIGHTING.equals(strMode)){
				groupListAsc.add(0, groupMap);
			}else{
				groupListAsc.add(groupMap);
			}
		}
		balanceTemplate.setGroupList(groupListAsc);
		
//		设置合同约定小数位修约方式
		roundModemap4contract = balanceTemplate.getRoundModeMap();

//		设置批次自动编码
		for(int i=0; i< sourcesList.size(); i++){
			Map<String,String> sRowMap = sourcesList.get(i);
			sRowMap.put(getMAP_KEY_BATCHCODE(), String.valueOf(i+1));
		}
		
//		重构结算批
		List<Map<String,String>> refactoringList = refactoringBatch(sourcesList, balanceTemplate);
//		结算结果
		SettlementResult sr = new SettlementResult();
//		计算结算明细结果
		List<Map<String,String>> detailsList = calculationDetails(refactoringList, balanceTemplate);
//		解构结算批  deconstruction
		List<Map<String,String>> resultList = deconstructionBatch(sourcesList, detailsList, balanceTemplate);
//		将明细结果赋值入结果集
		sr.setDetails(resultList);
//		计算结算汇总结果
		List<Map<String,String>> totalsList = calculationTotals(resultList);
		sr.setTotals(totalsList);
		return sr;
	}

	/**
	 * 根据结算模板得到每一批次每一种价格的结算明细
	 * @param sourcesList
	 * @param balanceTemplate
	 * @return
	 * @throws Exception
	 */
	public List<Map<String,String>> calculationDetails(List<Map<String,String>> sourcesList,SettlementTemplate balanceTemplate) throws Exception{
		if(sourcesList == null || sourcesList.isEmpty()){
			throw new Exception("结算数据为空");
		}
		if(balanceTemplate == null){
			throw new Exception("结算方案模板为空");
		}
//		定义变量
		List<Map<String,String>> detailsList = new ArrayList<Map<String,String>>();	//计算结果
		List<Map<String,String>> sourcestmpList = sourcesList;	//得到结算数据
		
//		设置批次自动编码
		for(int i=0; i< sourcestmpList.size(); i++){
			Map<String,String> sRowMap = sourcestmpList.get(i);
			sRowMap.put(getMAP_KEY_BATCHCODE(), String.valueOf(i+1));
		}
//		获得所有的结算指标代码并将其写入每一批次中，其值为null
		List<String> allkeys = getUsedTargetKeys(balanceTemplate, false);
		for(int i=0; i<allkeys.size(); i++){
			for(int j=0; j< sourcestmpList.size(); j++){
				Map<String,String> sRowMap = sourcestmpList.get(j);
				sRowMap.put(allkeys.get(i)+getSUFFIX_TARGET(), null);
			}
		}
//		List<Map<String,String>> sourcesgroup = ListTools.cloneListMap(sourcestmp);
//		获得需要汇总而不是加权平均的指标代码
		String strSumKey = propsmap.get("SUMKEY");
//		循环分组表达式
		for(int gr=0; gr< balanceTemplate.getGroupList().size(); gr++){
			List<Map<String,String>> sourcesGroupList = ListTools.cloneListMap(sourcestmpList);
			Map<String,String> groupRowMap = balanceTemplate.getGroupList().get(gr);
			validateGroupSet(groupRowMap);
			String strRownum = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_ROWNUM);
			String strEval = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_EVAL);
			String strEval4Index = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_EVAL4INDEX);
			String strEval4p = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_EVAL4PRICE);
			String strMode = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_MODE);
//			String priceType = (String)grouprow.get(SettlementOp.TMP_GROUP_MAP_KEY_PRICETYPE);	//费用类型
			String strQuantityKey = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_Quantity);	//数量结算依据指标代码
			//QuantityKey = propsmap.get(QuantityKey)==null?QuantityKey:propsmap.get(QuantityKey);
			String strWeightKey = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_Weight);	//质量结算依据加权权重
			String strQualityKey = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_Quality);	//质量结算依据指标代码
			String strEval4Quality = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_EVAL4Quality);	//结算热值公式
			
			strQualityKey = propsmap.get(strQualityKey)==null?strQualityKey:propsmap.get(strQualityKey);
			String strQualitysuffix = strQualityKey;
			if(strQualitysuffix==null){
				throw new Exception("结算模块配置不正确，未设置结算质量数据后缀。");
			}
			if(strEval4Index!=null && !"".equals(strEval4Index) && !"null".equalsIgnoreCase(strEval4Index)){
				strEval = strEval4Index;
			}
//			如果结算质量加权权重为空，则使用结算数量依据作为加权量
			if(strWeightKey==null || "".equals(strWeightKey)){
				strWeightKey = strQuantityKey;
			}
//			设置分组后的结算数量
			setQuantityKey(sourcesGroupList, getMAP_KEY_AMOUNT(), strQuantityKey);
//			设置分组后的质量加权权重
			setQuantityKey(sourcesGroupList, getMAP_KEY_WEIGHT(), strWeightKey);
//			结算质量指标Keys
			List<String> keysList = getUsedTargetKeys4GroupRow(balanceTemplate, strRownum);
//			根据给出的公式设置结算质量指标
			setQualityKeysByEval(sourcesGroupList, strMode, strEval4Quality, getMAP_KEY_WEIGHT());
//			设置结算质量指标
			setQualityKeys(sourcesGroupList, keysList, strQualitysuffix);
//			解析模板构建相应的分组批（价格批没有设置的话，默认与分组批相同）
			if(strEval4p == null || "".equals(strEval4p)){
				strEval4p = strEval;
			}
//			得到分组对应批
			List<Map<String,String>> targetBatchList = createBatchs(strEval, sourcesGroupList);
//			价格分组批
			List<Map<String,String>> priceBatchList = createBatchs(strEval4p, sourcesGroupList);
//			如果分组批没有数据则计算下一分组条件
			if(targetBatchList==null || targetBatchList.size()==0 || priceBatchList ==null || priceBatchList.size()==0){
				continue;
			}
//			将分组的信息计入基础批
			appendListMap(priceBatchList, groupRowMap, null);
			
			//计算价格得到结果
			if(SettlementOp.PRICE_MODE_WEIGHTING.equals(strMode)){	//计价方式加权
				//得到加权后的结算指标
				Map<String,String> targetMap = getSettlementTarget(strSumKey, targetBatchList, keysList, strQualitysuffix); //
				//指标增扣
				
				//写入计价指标
				appendListMap(priceBatchList, targetMap, getSUFFIX_TARGET());
				//数量增扣
				detailsList.addAll(deductionQuantity(balanceTemplate, strRownum, targetMap, priceBatchList));
				//循环计价条款得到计价map
				Map<String,String> priceMap = calculationPriceMap(strRownum, balanceTemplate.getPriceTermsList(), targetMap, sourcesGroupList);
				//将价格写入批次，不同价格写入同批次时，产生两个批次。
				List<Map<String,String>> resultList = writePriceList(priceBatchList, priceMap);
				//将结果写入details
				detailsList.addAll(resultList);
			}else{												//计价方式单批次
				//得到加权后的结算指标
				Map<String,String> weightTargetMapTmp = getSettlementTarget(strSumKey, targetBatchList, keysList, strQualitysuffix); //
				Map<String,String> weightTargetMap = new HashMap<String,String>();
				Iterator<Entry<String, String>> targetIterator = weightTargetMapTmp.entrySet().iterator();
				while(targetIterator.hasNext()){
					Entry<String, String> e = (Entry<String, String>)targetIterator.next();
					String strKey = e.getKey();
					if(!"合同价".equals(strKey) && !"合同热值".equals(strKey)){
						String strValue = e.getValue();
						weightTargetMap.put(strKey + propsmap.get("SUFFIX_WEIGHT"), strValue);
					}
				}
				for(int i = 0; i < priceBatchList.size(); i++){
					//统一算法克隆pricelist中的一条记录为一个新list使用新list进行数据的计算
					Map<String,String> priceBatchMap = priceBatchList.get(i);
					priceBatchMap.putAll(weightTargetMap);
					List<Map<String,String>> batchList = new ArrayList<Map<String,String>>();
					Map<String,String> tmpMap = new HashMap<String,String>();
					tmpMap.putAll(priceBatchMap);
					batchList.add(tmpMap);
					//得到结算指标
					Map<String,String> targetMap = getSettlementTarget(strSumKey, batchList, keysList, strQualitysuffix); //
					//指标增扣
					
					//写入计价指标
					appendListMap(batchList, targetMap, getSUFFIX_TARGET());
					//数量增扣
					detailsList.addAll(deductionQuantity(balanceTemplate, strRownum, targetMap, batchList));
					//循环计价条款得到计价map
					Map<String,String> priceMap = calculationPriceMap(strRownum, balanceTemplate.getPriceTermsList(), targetMap, sourcesGroupList);
					//将价格写入批次，不同价格写入同批次时，产生两个批次。
					List<Map<String,String>> resultList = writePriceList(batchList, priceMap);	
					//将结果写入details
					detailsList.addAll(resultList);
				}
			}
		}
		//处理增扣总额的逻辑
		deductionPrice(balanceTemplate, sourcestmpList, detailsList, strSumKey);
		if(detailsList.isEmpty()){
			throw new Exception("依据当前的结算条件及数据，无法结算。");
		}
		return detailsList;
	}
	
	/**
	 * 计算价格
	 * @param strRownum			分组行号
	 * @param priceTermsList	价格条款
	 * @param targetMap			指标值map
	 * @param sourcesList		解析公式变量使用的数据list
	 * @return
	 * @throws Exception
	 */
	private Map<String,String> calculationPriceMap(String strRownum, List<Map<String,String>> priceTermsList, Map<String,String> targetMap, List<Map<String,String>> sourcesList) throws Exception{
		Map<String,String> resultMap = new HashMap<String,String>(); 
		for(int i=0; i< priceTermsList.size(); i++){	//循环结算价格条款
			Map<String,String> priceRowMap = 
					priceTermsList.get(i);
			String strGroupNum = (String)priceRowMap.get(SettlementOp.TMP_TERMS_MAP_KEY_GROUPNUM);
			String strPriceCode = (String)priceRowMap.get(SettlementOp.TMP_TERMS_MAP_KEY_PRICECODE);
			if(strPriceCode.indexOf(",")!=-1){
				throw new Exception("结算方案模板价格条款不正确，计价分类为不能包含字符<,>。");
			}
			String strEval = (String)priceRowMap.get(SettlementOp.TMP_TERMS_MAP_KEY_EVAL);
			String strEval4Index = (String)priceRowMap.get(SettlementOp.TMP_TERMS_MAP_KEY_EVAL4INDEX);
			String strEvalCon = "";
			if(strEval4Index != null && !"".equals(strEval4Index) && !"null".equalsIgnoreCase(strEval4Index)){
				strEvalCon = strEval4Index;
			}else{
				strEvalCon = strEval;
			}
			while(strEvalCon.indexOf("}")!=-1){
				strEvalCon = resolveEval(strEvalCon, sourcesList);
			}
			String strFormula = (String)priceRowMap.get(SettlementOp.TMP_TERMS_MAP_KEY_FORMULA);
			String strFormulaParam = (String)priceRowMap.get(SettlementOp.TMP_TERMS_MAP_KEY_FORMULAPARA);
			if(SettlementOp.inArray(strGroupNum, strRownum, false)){	//[分组行号相等或分组行号为空]
				try{
					strEvalCon = SettlementOp.replaceFormulaParam(strEvalCon, strFormulaParam);
					if(Calculator.judgeCondition(strEvalCon, targetMap)){	//符合计价条件
						//List<Map<String,String>> groupBatch = ListTools.cloneListMap(sourcesList);
						//替换公式中指标的符号为正确的值
						strFormula = SettlementOp.replaceFormula(strFormula, targetMap);
						if(strFormulaParam!=null&& !"".equals(strFormulaParam))
							strFormula = SettlementOp.replaceFormulaParam(strFormula, strFormulaParam);
						//计算更新每批次单价
						double dbPrice = Calculator.getCalculatorValue(strFormula);
						
						dbPrice = CustomMaths.add(Double.parseDouble(resultMap.get(strPriceCode)==null?"0":resultMap.get(strPriceCode)), dbPrice);
						resultMap.put(strPriceCode, String.valueOf(dbPrice));
					}
				}catch(ScriptException s){
					throw new Exception("计算公式："+strEvalCon+" 出错");
				}
			}
		}
		return resultMap;
	}
	
	/**
	 * 根据单位公式转换值
	 * @param strKey
	 * @param strValue
	 * @param strOrginalUnit
	 * @return
	 * @throws Exception
	 */
	private String changeValue4Unit(String strKey, String strValue, String strOrginalUnit) throws Exception{
		String strNewValue = null;
		if(strOrginalUnit!=null && !strOrginalUnit.equals("")){
			String strConvertEval = propsmap.get(strOrginalUnit.toLowerCase());
			if(strConvertEval==null || "".equals(strConvertEval)){
				throw new Exception("配置错误，未设置单位转换公式。");
			}
			strConvertEval = strConvertEval.toLowerCase();
			if(strConvertEval.indexOf(strKey)!=-1){
				strNewValue = SettlementOp.UnitConvertIgnoreCase(strKey, strConvertEval, strValue);
			}
		}
		return strNewValue;
	}
	
	/**
	 * 根据各分组的费用类型计价分类写入总金额
	 * @param detailsList
	 * @return
	 * @throws Exception
	 */
	public List<Map<String,String>> calculationTotals(List<Map<String,String>> detailsList) throws Exception{
//		提取分组规则，得到结算分组结果的分组项。
		List<Map<String,String>> totalsList = new ArrayList<Map<String,String>>();
		List<String> groupList = getDistinctKeys(detailsList, SettlementOp.TMP_GROUP_MAP_KEY_PRICETYPE+","+SettlementOp.TMP_TERMS_MAP_KEY_PRICECODE);
//		循环分组项得到相应的单价及分类
		for(int i =0; i < groupList.size(); i++){
			String strGroupEval = groupList.get(i);
			String[] evalArr = strGroupEval.split(",");
			if(evalArr == null || evalArr.length!=2){
				continue;
			}
			Map<String,String> totalMap = new HashMap<String,String>();
			String strEval = SettlementOp.TMP_GROUP_MAP_KEY_PRICETYPE + SettlementOp.SIGN_EQUAL + "'" + evalArr[0] + "'&&" + SettlementOp.TMP_TERMS_MAP_KEY_PRICECODE + SettlementOp.SIGN_EQUAL +"'" + evalArr[1] + "'";
			List<Map<String,String>> batchList = SettlementOp.extract(strEval, detailsList);
			double dbAmountMoney = 0.0;
//			循环批次计算单批次总金额
			for(int m =0; m< batchList.size(); m++){
				Map<String,String> rowMap = batchList.get(m);
				String strPrice = rowMap.get(evalArr[1]);
				String strQuantity = rowMap.get(getMAP_KEY_AMOUNT());
				if(evalArr[1].equals(SettlementOp.DeductionPriceCode_Tonsofwater)) strQuantity = "1";
				dbAmountMoney = CustomMaths.add(Double.parseDouble(CustomMaths.mul(strQuantity, strPrice)), dbAmountMoney);
			}
//			写入分类及金额
			totalMap.put(SettlementOp.TMP_GROUP_MAP_KEY_PRICETYPE, evalArr[0]);
			totalMap.put(SettlementOp.TMP_TERMS_MAP_KEY_PRICECODE, evalArr[1]);
			totalMap.put(SettlementOp.MAP_KEY_MONEY, String.valueOf(dbAmountMoney));
			totalsList.add(totalMap);
		}
		return totalsList;
	}
	
	/**
	 * 不需要汇总的费用类型，计入批次
	 * @param sourcesList
	 * @return
	 * @throws Exception
	 */
	private List<Map<String,String>> countPriceCode(List<Map<String,String>> sourcesList) throws Exception{
		List<Map<String,String>> resultList = new ArrayList<Map<String,String>>();
		List<String> listPriceCode = getDistinctKeys(sourcesList, SettlementOp.TMP_TERMS_MAP_KEY_PRICECODE);
		for(int i=0; i < listPriceCode.size(); i++){
			String strPriceCode = listPriceCode.get(i);
			String strEval = SettlementOp.TMP_TERMS_MAP_KEY_PRICECODE + SettlementOp.SIGN_EQUAL + "'" + strPriceCode + "'";
			List<Map<String,String>> sourceList = null;
			try{
				sourceList = ListTools.cloneListMap(SettlementOp.extract(strEval, sourcesList));
			}catch(ScriptException s){
				throw new Exception("解析公式："+strEval+" 出错");
			}
			String strroundscale = roundingmap.get("price");
			int iroundscale = strroundscale==null||"".equals(strroundscale)?-1:Integer.parseInt(strroundscale);
			String strPrice = String.valueOf(SettlementOp.getWeightedValue(getMAP_KEY_AMOUNT(), strPriceCode, sourceList, getRoundModeWithKey("price"), iroundscale));
			for(int j=0; j< sourceList.size(); j++){
				Map<String,String> sRowMap = sourceList.get(j);
				String strAmount = sRowMap.get(getMAP_KEY_AMOUNT());
				String strAmountOfMoney = CustomMaths.mul(strAmount, strPrice);
				sRowMap.put(getMAP_KEY_PRICE(), strPrice);
				sRowMap.put(getMAP_KEY_AMOUNT_MONEY(), strAmountOfMoney);
			}
			resultList.addAll(sourceList);
		}
		return resultList;
	}
	
	/**
	 * 将各计价分类的单价加权值写入key值为price_计价分类中
	 * @param strPriceType
	 * @param strWeightedKey
	 * @param keysList
	 * @param sourcesList
	 * @param intPriceScale
	 * @return
	 */
	private Map<String,String> countWeightedPrice(String strPriceType, String strWeightedKey, List<String> keysList, List<Map<String,String>> sourcesList, int intPriceScale){
//		循环计价类型，得到各计价类型及总计（先加权后汇总、先汇总后加权）的值计入结果Map
		Map<String,String> priceMap = new HashMap<String,String>();
		double dbSumPrice = 0.0;
		for(int i=0; i< keysList.size(); i++){
			String strKey = keysList.get(i);
			if(strKey.equals(SettlementOp.DeductionPriceCode_Tonsofwater)){
				continue;
			}
			double dbPrice = SettlementOp.getWeightedValue(strWeightedKey, strKey, sourcesList, getRoundModeWithKey("price"), intPriceScale, Integer.parseInt(roundingmap.get("deaultPriceSacle")));
			if(strKey.equals(strPriceType)){
				priceMap.put("price_WeightedAfterSum_"+strKey, String.valueOf(dbPrice));
			}else{
				priceMap.put("price_"+strKey, String.valueOf(dbPrice));
				dbSumPrice = CustomMaths.add(dbPrice, dbSumPrice);
			}
		}
		if("round_new".equalsIgnoreCase(getRoundModeWithKey("price"))){
			dbSumPrice = CustomMaths.Round_new(dbSumPrice, intPriceScale);
		}else{
			dbSumPrice = CustomMaths.round(dbSumPrice, intPriceScale);
		}
		//dbSumPrice = CustomMaths.round(dbSumPrice, 2);
		priceMap.put("price_SumAfterWeighted_" + strPriceType, String.valueOf(dbSumPrice));
		return priceMap;
	}
	
	
	/**
	 * 根据表达式重新构造批次
	 * @param strEval
	 * @param sourcesList
	 * @return
	 * @throws Exception
	 */
	private List<Map<String,String>> createBatchs(String strEval, List<Map<String,String>> sourcesList) throws Exception{
		List<Map<String,String>> resultList = new ArrayList<Map<String,String>>();
		if(strEval==null || "".equals(strEval)){	//如果表达式为空默认所有批一个分组
			resultList = ListTools.cloneListMap(sourcesList);
		}else{
			while(strEval.indexOf("}")!=-1){
				strEval = resolveEval(strEval, sourcesList);//			解析模板中分组条件的变量
			}
			try{
				resultList = ListTools.cloneListMap(SettlementOp.extract(strEval, sourcesList));
			}catch(ScriptException s){
				throw new Exception("解析公式："+strEval+" 出错");
			}
		}
		return resultList;
	}
	
	/**
	 * 解构结算批
	 * @param sourcesList
	 * @param balanceTemplate
	 * @return
	 * @throws Exception
	 */
	private List<Map<String,String>> deconstructionBatch(List<Map<String,String>> sourcesList, List<Map<String,String>> detailsList, SettlementTemplate balanceTemplate) throws Exception{
		String strGroupByKey = balanceTemplate.getParaMap().get(SettlementOp.TMP_PARA_MAP_KEY_REFACTORING);
		List<Map<String,String>> resultList = new ArrayList<Map<String,String>>();
		if(strGroupByKey != null && !"".equals(strGroupByKey)){
			//循环details
			for(int i=0; i < detailsList.size(); i++){
				Map<String,String> detailMap = detailsList.get(i);
				//查找对应的sources 形成新的tmpList
				String strGroupValue = detailMap.get(strGroupByKey);
//				String eval = strGroupByKey + SettlementOp.SIGN_EQUAL + strGroupValue;
				String eval = "'" + strGroupByKey + "'" + SettlementOp.SIGN_EQUAL + "'" + strGroupValue + "'";
				List<Map<String,String>> tmplist = new ArrayList<Map<String,String>>();
				try {
					tmplist= ListTools.cloneListMap(ListTools.extract(eval, sourcesList));
				} catch (ScriptException e) {
					throw new Exception("分组公式解析错误。");
				}
				if(tmplist.isEmpty()){
					continue;
				}
				
				String strQuantityKey = detailMap.get(SettlementOp.TMP_GROUP_MAP_KEY_Quantity);
				//确认是否是数量增扣
				String strPriceCode = detailMap.get(SettlementOp.TMP_TERMS_MAP_KEY_PRICECODE);
				if(strPriceCode != null && strPriceCode.equals(SettlementOp.DeductionPriceCode_Tonsofwater)){
					String strPriceType = propsmap.get("WeightKeyWithPriceType");
					if(strPriceType == null){
						throw new Exception("配置错误，进行按日加权批处理时，结算加权量对应的费用类型(priceType)未配置。"); 
					}
					String strWeightKey = getQuantitykey(balanceTemplate, strPriceType);
					if(strWeightKey == null){
						throw new Exception("参数错误，在结算计价方案中找不到<" + strPriceType + ">对应的结算数量。"); 
					}
					//扣减量
					String strDeductionQuantity = detailMap.get(strPriceCode);
					//总量
					double dbTotalQuantity = SettlementOp.getSumValue(strWeightKey, tmplist, 2);
					double dbDeductionQuantity = strDeductionQuantity==null||"".equals(strDeductionQuantity)?0.0:Double.parseDouble(strDeductionQuantity);
					double dbRemainingQuantity = dbDeductionQuantity;
					for(int j=0; j< tmplist.size(); j++){
						Map<String,String> tmpMap = tmplist.get(j);
						//将tmpList对应map中的值putAll进新的map
						Map<String,String> resultMap = new HashMap<String,String>();
						resultMap.putAll(tmpMap);
						String strQuantity = resultMap.get(strWeightKey);
						double dbQuantity = strQuantity==null||"".equals(strQuantity)?0.0:Double.parseDouble(strQuantity);
						double dbRatio = CustomMaths.div(dbQuantity, dbTotalQuantity);
						double dbCurDeduction = 0.0; 
						if(j + 1 == tmplist.size()){
							dbCurDeduction = dbRemainingQuantity;
						}else{
							dbCurDeduction = CustomMaths.round(CustomMaths.mul(dbDeductionQuantity, dbRatio),2);
						}
						dbRemainingQuantity = CustomMaths.sub(dbRemainingQuantity, dbCurDeduction);
						//写入结算数量
						resultMap.put(getMAP_KEY_AMOUNT(), resultMap.get(strQuantityKey));
//						resultMap.put(SettlementOp.TMP_TERMS_MAP_KEY_PRICECODE, SettlementOp.DeductionPriceCode_Tonsofwater);
						appendMap(resultMap, detailMap);
						resultMap.put(SettlementOp.DeductionPriceCode_Tonsofwater, String.valueOf(dbCurDeduction));
						resultList.add(resultMap);
					}
					
				}else{
					//循环tmpList
					for(int j=0; j< tmplist.size(); j++){
						Map<String,String> tmpMap = tmplist.get(j);
						//将tmpList对应map中的值putAll进新的map
						Map<String,String> resultMap = new HashMap<String,String>();
						resultMap.putAll(tmpMap);
						//写入结算数量
						resultMap.put(getMAP_KEY_AMOUNT(), resultMap.get(strQuantityKey));
						//将details中的值添加进map（不替换原始值）
						appendMap(resultMap, detailMap);
						resultList.add(resultMap);
					}
				}
			}
		}else{
			resultList = detailsList;
		}
		return resultList;
	}
	
	/**
	 * 计算增扣款总额
	 * @param balanceTemplate	结算处理模板
	 * @param sourcesList		源数据list
	 * @param detailsList		明细结果list
	 * @param strSumKey			在计算计价指标时需要进行sum运算的指标
	 * @throws Exception
	 */
	private void deductionPrice(SettlementTemplate balanceTemplate, List<Map<String,String>> sourcesList, List<Map<String,String>> detailsList, String strSumKey) throws Exception{
		//扣减总煤款
		List<Map<String,String>> groupList = balanceTemplate.getGroupList();
		List<Map<String,String>> deductionList = balanceTemplate.getDeductionList();
		//循环增扣条款
		for(int d=0; d< deductionList.size(); d++){
			List<Map<String,String>> sourcesGroupList = ListTools.cloneListMap(sourcesList);
			Map<String,String> deductionMap = deductionList.get(d);
			String strDRownum = deductionMap.get(SettlementOp.TMP_TERMS_MAP_KEY_GROUPNUM);
			String strDPriceCode = (String)deductionMap.get(SettlementOp.TMP_TERMS_MAP_KEY_PRICECODE);
			String strDEval = (String)deductionMap.get(SettlementOp.TMP_TERMS_MAP_KEY_EVAL);
			String strDEval4Index =  (String)deductionMap.get(SettlementOp.TMP_TERMS_MAP_KEY_EVAL4INDEX);
			String strDFormula = (String)deductionMap.get(SettlementOp.TMP_TERMS_MAP_KEY_FORMULA);
			String strDFormulaParam = (String)deductionMap.get(SettlementOp.TMP_TERMS_MAP_KEY_FORMULAPARA);
			if(strDEval4Index != null && !"".equals(strDEval4Index)){
				strDEval = strDEval4Index;
			}
			if(SettlementOp.DeductionPriceCode_Total.equals(strDPriceCode)){
				Map<String,String> groupRowMap = SettlementOp.getGroupMap4Rownum(groupList, strDRownum);
				validateGroupSet(groupRowMap);
				String strRownum = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_ROWNUM);
				String strEval = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_EVAL);
				String strEval4Index = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_EVAL4INDEX);
				String strEval4p = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_EVAL4PRICE);
				String strMode = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_MODE);
				String strPriceType = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_PRICETYPE);	//费用类型
				String strQuantityKey = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_Quantity);	//数量结算依据指标代码
				//QuantityKey = propsmap.get(QuantityKey)==null?QuantityKey:propsmap.get(QuantityKey);
				String strWeightKey = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_Weight);	//质量结算依据加权权重
				String strQualityKey = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_Quality);	//质量结算依据指标代码
				strQualityKey = propsmap.get(strQualityKey)==null?strQualityKey:propsmap.get(strQualityKey);
				String strQualitySuffix = strQualityKey;
				if(strEval4Index != null && !"".equals(strEval4Index) && !"null".equalsIgnoreCase(strEval4Index)){
					strEval = strEval4Index;
				}
//				如果结算质量加权权重为空，则使用结算数量依据作为加权量
				if(strWeightKey==null || "".equals(strWeightKey)){
					strWeightKey = strQuantityKey;
				}
				if(strQualitySuffix==null){
					throw new Exception("结算模块配置不正确，未设置结算质量数据后缀。");
				}
//				设置分组后的结算数量
				setQuantityKey(sourcesGroupList, getMAP_KEY_AMOUNT(), strQuantityKey);
//				设置分组后的质量加权权重
				setQuantityKey(sourcesGroupList, getMAP_KEY_WEIGHT(), strWeightKey);
//						结算质量指标Keys
				List<String> keysList = getUsedTargetKeys4GroupRow(balanceTemplate, strRownum);
//						设置结算质量指标
				setQualityKeys(sourcesGroupList, keysList, strQualitySuffix);
//						解析模板构建相应的分组批（价格批没有设置的话，默认与分组批相同）
				if(strEval4p == null || "".equals(strEval4p)){
					strEval4p = strEval;
				}
//						得到分组对应批
				List<Map<String,String>> targetBatchList = createBatchs(strEval, sourcesGroupList);
//						价格分组批
				List<Map<String,String>> priceBatchList = createBatchs(strEval4p, sourcesGroupList);
//						如果分组批没有数据则计算下一分组条件
				if(targetBatchList==null || targetBatchList.size()==0 || priceBatchList ==null || priceBatchList.size()==0){
					continue;
				}
//				将分组的信息计入基础批
				appendListMap(priceBatchList, groupRowMap, null);
				Map<String,String> paramMap = new HashMap<String, String>();
//				循环计价明细计算出每一批的总金额（按费用类别过滤）
				Map<String,String> batchAmountMap = getBatchAmountMap(detailsList, strPriceType, null);
				double dbTotalAmount = MapUtils.sumFloatValue(batchAmountMap);
				paramMap.put(getMAP_KEY_TMP_TOTALMONEY(), String.valueOf(dbTotalAmount));
//				循环计价明细计算出结算总量（按费用类别过滤）
				Map<String,String> batchQuantityMap = getBatchQuantityMap(detailsList, strPriceType, null);
				double dbTotalQuantity = MapUtils.sumFloatValue(batchQuantityMap);
				paramMap.put(getMAP_KEY_TMP_TOTALQUANTITY(), String.valueOf(dbTotalQuantity));
//				循环计价明细计算出方式为加权平均的每一批的总金额（按费用类别过滤）
				Map<String,String> batchAmountMap4W = getBatchAmountMap(detailsList, strPriceType, SettlementOp.PRICE_MODE_WEIGHTING);
				double dbTotalAmount4W = MapUtils.sumFloatValue(batchAmountMap4W);
				paramMap.put(getMAP_KEY_TMP_TOTALMONEY4W(), String.valueOf(dbTotalAmount4W));
//				循环计价明细计算出加权结算总量（按费用类别过滤）
				Map<String,String> batchQuantityMap4W = getBatchQuantityMap(detailsList, strPriceType, SettlementOp.PRICE_MODE_WEIGHTING);
				double dbTotalQuantity4W = MapUtils.sumFloatValue(batchQuantityMap4W);
				paramMap.put(getMAP_KEY_TMP_TOTALQUANTITY4W(), String.valueOf(dbTotalQuantity4W));
				
				//计算价格得到结果
				if(SettlementOp.PRICE_MODE_WEIGHTING.equals(strMode)){	//计价方式加权
					//得到结算指标
					Map<String,String> targetMap = getSettlementTarget(strSumKey, targetBatchList, keysList, strQualitySuffix); //
					
					//符合扣减条件
					if(Calculator.judgeCondition(strDEval, targetMap)){
						for(int i = 0; i < priceBatchList.size(); i++){
							Map<String,String> batchMap = priceBatchList.get(i);
							String strBatchCode = batchMap.get(getMAP_KEY_BATCHCODE()); 
							String strAmount = batchAmountMap.get(strBatchCode);	//获得该批次总金额
							String strQuantity = batchMap.get(getMAP_KEY_AMOUNT());	
							paramMap.put(getMAP_KEY_TMP_BATCHMONEY(), strAmount);
							paramMap.put(getMAP_KEY_TMP_BATCHQUANTITY(), strQuantity);
							//String strPrice = CustomMaths.div(strAmount, strQuantity, 10);
							//替换固定参数pricetype(在增扣总额中，总煤款使用priceType替换)
							//targetMap.put(strPriceType, strPrice);
							//构造公式,替换指标
							String strDFormulaTmp = strDFormula;
							targetMap.putAll(paramMap);
							strDFormulaTmp = SettlementOp.replaceFormula(strDFormulaTmp, targetMap);
//							strDFormulaTmp = SettlementOp.replaceFormula(strDFormulaTmp, paramMap);
							//替换合同中公式中参数
							if(strDFormulaParam!=null&& !"".equals(strDFormulaParam))
								strDFormulaTmp = SettlementOp.replaceFormulaParam(strDFormulaTmp, strDFormulaParam);
							//计算更新每批次单价
							double dbRatio = Calculator.getCalculatorValue(strDFormulaTmp);
//							String strPrice = CustomMaths.div(CustomMaths.mul(strAmount, String.valueOf(dbRatio)),strQuantity,10);
							//将计价分类及计价分类对应的单价写入
							batchMap.put(SettlementOp.TMP_TERMS_MAP_KEY_PRICECODE, strDPriceCode);
							batchMap.put(strDPriceCode, String.valueOf(dbRatio));
						}
						detailsList.addAll(priceBatchList);
					}
				}else{
					for(int p = 0; p < priceBatchList.size(); p++){
						//统一算法克隆pricelist中的一条记录为一个新list使用新list进行数据的计算
						Map<String,String> priceBatchMap = priceBatchList.get(p);
						List<Map<String,String>> batchList = new ArrayList<Map<String,String>>();
						Map<String,String> tmpMap = new HashMap<String,String>();
						tmpMap.putAll(priceBatchMap);
						batchList.add(tmpMap);
						//得到结算指标
						Map<String,String> targetMap = getSettlementTarget(strSumKey, batchList, keysList, strQualitySuffix); //
						//符合扣减条件
						if(Calculator.judgeCondition(strDEval, targetMap)){
							for(int i = 0; i < batchList.size(); i++){
								Map<String,String> batchMap = batchList.get(i);
								String strBatchCode = batchMap.get(getMAP_KEY_BATCHCODE()); 
								String strAmount = batchAmountMap.get(strBatchCode);	//获得该批次总金额
								String strQuantity = batchMap.get(getMAP_KEY_AMOUNT());	
								paramMap.put(getMAP_KEY_TMP_BATCHMONEY(), strAmount);
								paramMap.put(getMAP_KEY_TMP_BATCHQUANTITY(), strQuantity);
								//String strPrice = CustomMaths.div(strAmount, strQuantity, 10);
								//替换固定参数pricetype(在增扣总额中，总煤款使用priceType替换)
								//targetMap.put(strPriceType, strPrice);
								//构造公式,替换指标
								String strDFormulaTmp = strDFormula;
								targetMap.putAll(paramMap);
								strDFormulaTmp = SettlementOp.replaceFormula(strDFormulaTmp, targetMap);
//								strDFormulaTmp = SettlementOp.replaceFormula(strDFormulaTmp, paramMap);
								//替换合同中公式中参数
								if(strDFormulaParam!=null&& !"".equals(strDFormulaParam))
									strDFormulaTmp = SettlementOp.replaceFormulaParam(strDFormulaTmp, strDFormulaParam);
								//计算更新每批次单价
								//double dbPrice = Calculator.getCalculatorValue(strDFormulaTmp);
								double dbRatio = Calculator.getCalculatorValue(strDFormulaTmp);
//								String strPrice = CustomMaths.div(CustomMaths.mul(strAmount, String.valueOf(dbRatio)),strQuantity,10);
								//将计价分类及计价分类对应的单价写入
								batchMap.put(SettlementOp.TMP_TERMS_MAP_KEY_PRICECODE, strDPriceCode);
								batchMap.put(strDPriceCode, String.valueOf(dbRatio));
							}
							detailsList.addAll(batchList);
						}
					}
				}
			}
		}
	}
	
	/**
	 * 增扣数量处理
	 * @param balanceTemplate		结算模板
	 * @param strRownum				结算分组条件行号
	 * @param targetMap				结算指标
	 * @param priceBatchList		计价批次
	 * @throws Exception
	 */
	private List<Map<String,String>> deductionQuantity(SettlementTemplate balanceTemplate, String strRownum, Map<String,String> targetMap, List<Map<String,String>> priceBatchList) throws Exception{
		List<Map<String,String>> resultList = new ArrayList<Map<String,String>>();
		for(int d=0; d< balanceTemplate.getDeductionList().size(); d++){
			Map<String, String> deductionMap = balanceTemplate.getDeductionList().get(d);
			String strDRownum = deductionMap.get(SettlementOp.TMP_TERMS_MAP_KEY_GROUPNUM);
			String strDPriceCode = deductionMap.get(SettlementOp.TMP_TERMS_MAP_KEY_PRICECODE);
			String strDEval = (String)deductionMap.get(SettlementOp.TMP_TERMS_MAP_KEY_EVAL);
			String strDEval4Index = (String)deductionMap.get(SettlementOp.TMP_TERMS_MAP_KEY_EVAL4INDEX);
			String strDFormula = (String)deductionMap.get(SettlementOp.TMP_TERMS_MAP_KEY_FORMULA);
			String strDFormulaParam = (String)deductionMap.get(SettlementOp.TMP_TERMS_MAP_KEY_FORMULAPARA);
			String strDEvalCon = "";
			//strDEval4Index 优先 特殊处理，
			if(strDEval4Index != null && !"".equals(strDEval4Index)){
				strDEvalCon = strDEval4Index;
			}else{
				strDEvalCon = strDEval;
			}
			if(strDRownum !=null && strDPriceCode!= null)
				if(strDRownum.equals(strRownum) && strDPriceCode.equals(SettlementOp.DeductionPriceCode_Tonsofwater)){
					if(Calculator.judgeCondition(strDEvalCon, targetMap)){
						String strDFormulaTmp = strDFormula;
						strDFormulaTmp = SettlementOp.replaceFormula(strDFormulaTmp, targetMap);
						//替换合同中公式中参数
						if(strDFormulaParam!=null&& !"".equals(strDFormulaParam))
							strDFormulaTmp = SettlementOp.replaceFormulaParam(strDFormulaTmp, strDFormulaParam);
						//计算更新每批次数量
						double dbRatio = Calculator.getCalculatorValue(strDFormulaTmp);
						for(int i=0; i< priceBatchList.size(); i++){
							Map<String, String> pbMap = priceBatchList.get(i);
							Map<String, String> tmpMap = new HashMap<String, String>();
							tmpMap.putAll(pbMap);
							String strQuantity = tmpMap.get(getMAP_KEY_AMOUNT());
//							double dbQuantity = strQuantity ==null|| "".equals(strQuantity) ? 0.0: Double.parseDouble(strQuantity);
							String strDedQuantity = CustomMaths.mul(strQuantity, String.valueOf(dbRatio));
							String strroundscale = roundingmap.get(SettlementOp.DeductionPriceCode_Tonsofwater);
							int iroundscale = strroundscale==null||"".equals(strroundscale)?-1:Integer.parseInt(strroundscale);
							if(iroundscale!=-1){
								strDedQuantity = String.valueOf(CustomMaths.round(strDedQuantity, iroundscale));
							}
//							double dbDedQuantity = strDedQuantity ==null|| "".equals(strDedQuantity) ? 0.0: Double.parseDouble(strDedQuantity);
//							double dbCurQuantity = CustomMaths.add(dbQuantity, dbDedQuantity);
							tmpMap.put(SettlementOp.TMP_TERMS_MAP_KEY_PRICECODE, strDPriceCode);
							tmpMap.put(SettlementOp.DeductionPriceCode_Tonsofwater, strDedQuantity);
							resultList.add(tmpMap);
						}
					}
				}
		}
		return resultList;
	}
	
	/**
	 * 得到每个批次的strPriceType费用项目下strMode对应的的总金额
	 * @param sourcesList
	 * @param strPriceType
	 * @return
	 */
	private Map<String,String> getBatchAmountMap(List<Map<String,String>> sourcesList, String strPriceType, String strMode){
		Map<String,String> resultMap = new HashMap<String,String>();
		for(int i=0;i<sourcesList.size(); i++){
			Map<String,String> batchMap = sourcesList.get(i);
			String strBatchCode = batchMap.get(getMAP_KEY_BATCHCODE());
			String strPriceType4Batch = batchMap.get(SettlementOp.TMP_GROUP_MAP_KEY_PRICETYPE); 
			String strPriceCode = batchMap.get(SettlementOp.TMP_TERMS_MAP_KEY_PRICECODE);
			String strMode4Batch = batchMap.get(SettlementOp.TMP_GROUP_MAP_KEY_MODE);
			if(strPriceType4Batch.equals(strPriceType)){	//按照与增扣款相同的费用类型统计
				if(strMode == null || strMode.equals(strMode4Batch)){
					String strPrice = batchMap.get(strPriceCode);	//该批次单价
					String strBatchAmount = resultMap.get(strBatchCode);	//该批次已记录金额
					double dbBatchAmount = strBatchAmount==null||"".equals(strBatchAmount)?0:Double.parseDouble(strBatchAmount);
					String strQuantity = batchMap.get(getMAP_KEY_AMOUNT());	//该批次结算数量
					String strAmount = CustomMaths.mul(strQuantity, strPrice);
					double dbAmount = strAmount==null||"".equals(strAmount)?0:Double.parseDouble(strAmount);
					strBatchAmount = String.valueOf(CustomMaths.add(dbBatchAmount, dbAmount));
					resultMap.put(strBatchCode, strBatchAmount);
				}
			}
		}
		return resultMap;
	}
	
	/**
	 * 得到每个批次的strPriceType费用项目下strMode对应的总数量
	 * @param sourcesList
	 * @param strPriceType
	 * @return
	 */
	private Map<String,String> getBatchQuantityMap(List<Map<String,String>> sourcesList, String strPriceType, String strMode){
		Map<String,String> resultMap = new HashMap<String,String>();
		for(int i=0;i<sourcesList.size(); i++){
			Map<String,String> batchMap = sourcesList.get(i);
			String strBatchCode = batchMap.get(getMAP_KEY_BATCHCODE());
			String strPriceType4Batch = batchMap.get(SettlementOp.TMP_GROUP_MAP_KEY_PRICETYPE); 
			String strMode4Batch = batchMap.get(SettlementOp.TMP_GROUP_MAP_KEY_MODE);
			if(strPriceType4Batch.equals(strPriceType)){	//按照与增扣款相同的费用类型统计
				if(strMode == null || strMode.equals(strMode4Batch)){
					String strQuantity = batchMap.get(getMAP_KEY_AMOUNT());	//该批次结算数量
					resultMap.put(strBatchCode, strQuantity);
				}
			}
		}
		return resultMap;
	}
	
	public String getDeductionName(){		//得到增扣名称key
		return propsmap.get("DeductionName");
	}
	
	/**
	 * 得到批次中strkeys相应的费用类型及计价分类
	 * @param sourcesList
	 * @param strkeys
	 * @return
	 */
	public List<String> getDistinctKeys(List<Map<String,String>> sourcesList, String strkeys){
		List<String> keysList = new ArrayList<String>();
		String[] keyArr = strkeys.split(",");
		for(int i = 0; i < sourcesList.size(); i++){
			Map<String,String> sRowMap = sourcesList.get(i);
			String strkey = "";
			for(int j =0; j < keyArr.length; j ++){
				strkey += sRowMap.get(keyArr[j]) +",";
			}
			strkey = strkey.substring(0, strkey.length()-1);
			keysList.add(strkey);			
		}
		List<String> resultList = new ArrayList<String>(new HashSet<String>(keysList));
		return resultList;
	}
	
	public String getMAP_KEY_AMOUNT(){				//结算数量key
		return propsmap.get("MAP_KEY_AMOUNT");
	}
	
	public String getMAP_KEY_WEIGHT(){				//质量加权权重key
		return propsmap.get("MAP_KEY_WEIGHT");
	}
	
	public String getMAP_KEY_AMOUNT_MONEY(){		//结算金额key
		return propsmap.get("MAP_KEY_AMOUNT_MONEY");
	}
	
	public String getMAP_KEY_BATCHCODE(){		//自定义batchcode，key
		return propsmap.get("MAP_KEY_BATCHCODE");
	}
	
	public String getMAP_KEY_PRICE(){				//结算单价key
		return propsmap.get("MAP_KEY_PRICE");
	}
	
	public String getMAP_KEY_PRICECODE(){			//pricecode 的key
		return propsmap.get("MAP_KEY_PRICECODE");
	}
	
	public String getMAP_KEY_PRICETYPE(){			//pricetype 的key
		return propsmap.get("MAP_KEY_PRICETYPE");
	}

	public String getPriceName(){		//得到计价名称key
		return propsmap.get("PriceName");
	}
	
	public String getPriceScale(){					//得到价格小数位
		return roundingmap.get("PriceScale");
	}
	
	public String getZeroSwitch(){					//得到价格下限0的开关
		return propsmap.get("Zero_switch");
	}
	
	public String getMAP_KEY_TMP_BATCHMONEY(){					//当前批次的金额KEY
		return propsmap.get("MAP_KEY_TMP_BATCHMONEY");
	}
	
	public String getMAP_KEY_TMP_TOTALMONEY(){					//当前总金额KEY
		return propsmap.get("MAP_KEY_TMP_TOTALMONEY");
	}
	
	public String getMAP_KEY_TMP_TOTALQUANTITY(){					//当前总结算量
		return propsmap.get("MAP_KEY_TMP_TOTALQUANTITY");
	}
	
	public String getMAP_KEY_TMP_TOTALMONEY4W(){					//当前加权金额KEY
		return propsmap.get("MAP_KEY_TMP_TOTALMONEY4W");		
	}
	
	public String getMAP_KEY_TMP_TOTALQUANTITY4W(){					//当前加权结算量
		return propsmap.get("MAP_KEY_TMP_TOTALQUANTITY4W");		
	}
	
	public String getMAP_KEY_TMP_BATCHQUANTITY(){					//当前批次结算数量
		return propsmap.get("MAP_KEY_TMP_BATCHQUANTITY");
	}
	
	/**
	 * 得到价格条款中使用的指标
	 * @param balanceTemplate
	 * @param rownum
	 * @return
	 */
	private List<String> getPriceTermsKeys(SettlementTemplate balanceTemplate, String strRownum){
		List<String> resultkeysList = new ArrayList<String>();
		List<String> excludeKeysList = new ArrayList<String>();	//公式的key
		for(int i=0 ; i<Calculator.funcArray.length; i++){
			excludeKeysList.add(Calculator.funcArray[i]);
		}
		
		for(int i = 0; i< balanceTemplate.getPriceTermsList().size(); i++){
			Map<String,String> m = balanceTemplate.getPriceTermsList().get(i);
			if(strRownum.equalsIgnoreCase(m.get(SettlementOp.TMP_TERMS_MAP_KEY_GROUPNUM))){
				String strEval = m.get(SettlementOp.TMP_TERMS_MAP_KEY_EVAL);
				String strEval4Index = m.get(SettlementOp.TMP_TERMS_MAP_KEY_EVAL4INDEX);
				String strFormula = m.get(SettlementOp.TMP_TERMS_MAP_KEY_FORMULA);
				String strFormulapara = m.get(SettlementOp.TMP_TERMS_MAP_KEY_FORMULAPARA);
				resultkeysList.addAll(SettlementOp.getConditionKeys((strEval==null?"":strEval).toLowerCase()));
				resultkeysList.addAll(SettlementOp.getConditionKeys((strEval4Index==null|| "null".equalsIgnoreCase(strEval4Index)?"":strEval4Index).toLowerCase()));
				resultkeysList.addAll(SettlementOp.getConditionKeys((strFormula==null?"":strFormula).toLowerCase()));
				excludeKeysList.addAll(SettlementOp.getConditionKeys((strFormulapara==null?"":strFormulapara).toLowerCase()));
			}
		}
		for(int i = 0; i< balanceTemplate.getDeductionList().size(); i++){
			Map<String,String> m = balanceTemplate.getDeductionList().get(i);
			if(strRownum.equalsIgnoreCase(m.get(SettlementOp.TMP_TERMS_MAP_KEY_GROUPNUM))){
				String strEval = m.get(SettlementOp.TMP_TERMS_MAP_KEY_EVAL);
				String strEval4Index = m.get(SettlementOp.TMP_TERMS_MAP_KEY_EVAL4INDEX);
				String strFormula = m.get(SettlementOp.TMP_TERMS_MAP_KEY_FORMULA);
				String strFormulapara = m.get(SettlementOp.TMP_TERMS_MAP_KEY_FORMULAPARA);
				resultkeysList.addAll(SettlementOp.getConditionKeys((strEval==null?"":strEval).toLowerCase()));
				resultkeysList.addAll(SettlementOp.getConditionKeys((strEval4Index==null ||"null".equalsIgnoreCase(strEval4Index)?"":strEval4Index).toLowerCase()));
				resultkeysList.addAll(SettlementOp.getConditionKeys((strFormula==null?"":strFormula).toLowerCase()));
				excludeKeysList.addAll(SettlementOp.getConditionKeys((strFormulapara==null?"":strFormulapara).toLowerCase()));
			}
		}
		if(resultkeysList.size()==0) return null;
		resultkeysList = new ArrayList<String>(new HashSet<String>(resultkeysList));
		resultkeysList.removeAll(excludeKeysList);
		return resultkeysList;
	}
	
	/**
	 * 获得结算类型下的结算量的指标key
	 * @param balanceTemplate
	 * @param strPriceType
	 * @return
	 */
	private String getQuantitykey(SettlementTemplate balanceTemplate, String strPriceType){
		String strQuantitykey = null;
		if(strPriceType==null) return null;
		for(int i=0; i < balanceTemplate.getGroupList().size(); i++){
			Map<String,String> groupMap = balanceTemplate.getGroupList().get(i);
			if(strPriceType.equalsIgnoreCase(groupMap.get(SettlementOp.TMP_GROUP_MAP_KEY_PRICETYPE)))
				strQuantitykey = groupMap.get(SettlementOp.TMP_GROUP_MAP_KEY_Quantity);
		}
		return strQuantitykey;
	}
	
	/**
	 * 获得结算类型下的质量加权指标key
	 * @param balanceTemplate
	 * @param strPriceType
	 * @return
	 */
	private String getQualityWeightkey(SettlementTemplate balanceTemplate, String strPriceType){
		String strQualityWeightkey = null;
		String strQuantitykey = null;
		if(strPriceType==null) return null;
		for(int i=0; i < balanceTemplate.getGroupList().size(); i++){
			Map<String,String> groupMap = balanceTemplate.getGroupList().get(i);
			if(strPriceType.equalsIgnoreCase(groupMap.get(SettlementOp.TMP_GROUP_MAP_KEY_PRICETYPE))){
				strQuantitykey = groupMap.get(SettlementOp.TMP_GROUP_MAP_KEY_Quantity);
				strQualityWeightkey = groupMap.get(SettlementOp.TMP_GROUP_MAP_KEY_Weight);
			}
		}
		if(strQualityWeightkey==null || "".equals(strQualityWeightkey) || "null".equalsIgnoreCase(strQualityWeightkey)){
			strQualityWeightkey = strQuantitykey;
		}
		return strQualityWeightkey;
	}
	
	/**
	 * 根据结算批次明细汇总得到用友系统需要的数据格式
	 * @param sourcesList
	 * @param detailsList
	 * @param strSettlementType
	 * @return
	 * @throws Exception
	 */
	public List<Map<String,String>> getResult4Batchs(List<Map<String,String>> sourcesList,List<Map<String,String>> detailsList, String strSettlementType) throws Exception{
//		构建一个与sources同样长度的定长List
		List<Map<String,String>> templateList = new ArrayList<Map<String,String>>();
		List<Map<String,String>> resultList = new ArrayList<Map<String,String>>();
		Map<String,String> tmpMap = new HashMap<String,String>();
		for(int i=0; i< sourcesList.size(); i++){
			templateList.add(null);
		}
//		提取费用项目，得到结算分组结果的条件
		List<String> groupList = getDistinctKeys(detailsList, SettlementOp.TMP_GROUP_MAP_KEY_PRICETYPE);
//		循环费用项目得到分组对应的批次
		for(int i =0; i < groupList.size(); i++){
			String strPriceType = groupList.get(i);
			String strEval = SettlementOp.TMP_GROUP_MAP_KEY_PRICETYPE + SettlementOp.SIGN_EQUAL + "'" + strPriceType + "'";
			List<Map<String,String>> extractList = null;
			try{
				extractList = ListTools.cloneListMap(SettlementOp.extract(strEval, detailsList));
			}catch(ScriptException s){
				throw new Exception("解析公式："+strEval+" 出错");
			}
			//如果是需要进行汇总的费用类型
			if(SettlementOp.inArray(getSUMMARYTYPE(), strPriceType, false)){
				List<Map<String,String>> tmpList = ListTools.cloneListMap(templateList);
//				按照批次统计各批次的计价单价，并将总价写入key值为strPriceType中
				List<String> keysList = writeBatchPrice(strPriceType, tmpList, extractList);
				tmpList.removeAll(Collections.singleton(null));
//				总价小数修约
				int totalPriceScale = Integer.parseInt(roundingmap.get("totalPriceScale"));
				for(Map<String,String> e : tmpList){
					String strPrice = e.get(strPriceType);
					double dbprice = Double.parseDouble(strPrice);
					dbprice = CustomMaths.round(dbprice, totalPriceScale);
					e.put(strPriceType, String.valueOf(dbprice));
				}
				
//				处理增扣数量
				writeBatchQuantity(tmpList);
//				将各计价分类的单价加权值写入key值为price_计价分类中
				String strroundscale = roundingmap.get("price");
				int iroundscale = strroundscale==null||"".equals(strroundscale)?2:Integer.parseInt(strroundscale);
				Map<String,String> priceMap = countWeightedPrice(strPriceType, getMAP_KEY_AMOUNT(), keysList, tmpList, iroundscale);
//				根据结算类型写入price、Amountofcoal
				String strPrice = "";
				String strPriceKey = "";
				if(SettlementType001.equals(strSettlementType)){	//先将热值等考核价格加权后相加 然后算出总额
					strPrice = priceMap.get("price_SumAfterWeighted_" + strPriceType);
					strPriceKey = "price_SumAfterWeighted_" + strPriceType;
				}else if(SettlementType002.equals(strSettlementType)){	//先将热值等考核价格相加后  算出总额 最后得出单价
					strPrice = priceMap.get("price_WeightedAfterSum_" + strPriceType);
					strPriceKey = strPriceType;
				}
				priceMap.put(getMAP_KEY_PRICE(), strPrice);
				appendListMap(tmpList, priceMap, null);
				writeBatchsMoney(tmpList, strPriceKey);
				if(getZeroSwitch().equalsIgnoreCase("on")){
					RemoveNegativeNumbers(tmpList, new String[]{"price_SumAfterWeighted_" + strPriceType, "price_WeightedAfterSum_" + strPriceType, getMAP_KEY_PRICE(), getMAP_KEY_AMOUNT_MONEY()});
				}
				resultList.addAll(tmpList);
				
			}else{	//不需要汇总的费用类型
				resultList.addAll(countPriceCode(extractList));
			}
		}
		return resultList;
	}
	
	/**
	 * 移除负数将负数替换为0
	 * @param resultList
	 * @param strkeys
	 */
	private void RemoveNegativeNumbers(List<Map<String,String>> resultList, String[] strkeys){
		if(resultList == null || strkeys == null){
			return;
		}
		for(Map<String,String> map : resultList){
			for(String strkey: strkeys){
				String strvalue = map.get(strkey);
				if(strvalue != null && CustomMaths.isNumeric(strvalue)){
					if(Double.parseDouble(strvalue)<0) map.put(strkey, "0");
				}
			}
		}
	}
	
	/**
	 * @param strKey	指标
	 * @return
	 */
	private String getRoundModeWithKey(String strKey){
		String strRoundMode = "round";
		String strRoundModeTemp = null;
		if(roundModemap4System != null){
			strRoundModeTemp = roundModemap4System.get(strKey);
		}
		if(roundModemap4contract != null){
			strRoundModeTemp = roundModemap4contract.get(strKey);
		}
		if(strRoundModeTemp != null && "".equals(strRoundModeTemp)){
			strRoundMode = strRoundModeTemp;
		}
		return strRoundMode;
	}
	
	
	/**
	 * 得到根据结算量加权后的结算指标Map
	 * @param sourcesList
	 * @param termsKeysList
	 * @param strQualitySuffix
	 * @return
	 * @throws Exception
	 */
	private Map<String,String> getSettlementTarget(String strSumkey, List<Map<String,String>> sourcesList, List<String> termsKeysList, String strQualitySuffix) throws Exception{
		List<String> tkList = new ArrayList<String>();
		tkList.addAll(termsKeysList);
		//得到特殊处理的MAP
		Map<String,String> keyopMap = new HashMap<String,String>();
		Map<String,String> evalMap = new HashMap<String,String>();
		Map<String,String> resultMap = new HashMap<String,String>();
		if("on".equalsIgnoreCase(propsmap.get("Special_switch"))){
			String strKeys = propsmap.get("Special_KEYS");
			String strKeyOP = propsmap.get("Special_KEYOP");
			String strEval = propsmap.get("Special_EVAL");
			String [] keyArr = strKeys.split("#");
			String [] keyopArr = strKeyOP.split("#");
			String [] evalArr = strEval.split("#");
			if(keyArr.length != evalArr.length || keyArr.length != keyopArr.length){
				throw new Exception("配置文件中关于结算指标特殊处理的配置项有误。");
			}
			for(int s=0; s< keyArr.length; s++){
				String key = keyArr[s];
				String op = keyopArr[s];
				String eval = evalArr[s];
				keyopMap.put(key, op);
				evalMap.put(key, eval);
			}
		}
		
		//构建计算加权指标的List
		List<Map<String,String>> targetList = new ArrayList<Map<String,String>>();
		for(int i=0; i< sourcesList.size(); i++){
			Map<String,String> sRowMap = sourcesList.get(i);		//原listmap
			Map<String,String> targetMap = new HashMap<String,String>();		//新map
//			String strWeightKey = sRowMap.get(getMAP_KEY_WEIGHT());
			String strWeight = sRowMap.get(getMAP_KEY_WEIGHT());
			targetMap.put(getMAP_KEY_WEIGHT(), strWeight);
			//循环指标并进行赋值
			for(int k=0; k< tkList.size(); k++){
				String strKey = tkList.get(k);
				String strValue = sRowMap.get(strKey);
				if(strValue==null || "".equals(strValue)){
					continue;
				}
				if(!CustomMaths.isNumeric(strValue)){
					resultMap.put(strKey, strValue);
					tkList.remove(k--);
					continue;
				}
				String op = keyopMap.get(strKey);
				if(op != null){
					String strOValue = sRowMap.get(strKey + strQualitySuffix);
					op = op.replaceAll(strKey, strOValue);
					double dbValue = Calculator.getCalculatorValue(op);
					strValue = String.valueOf(dbValue);
				}
				targetMap.put(strKey, strValue);
			}
			targetList.add(targetMap);
		}
		//循环指标得到加权结果
		
		for(int k=0; k< tkList.size(); k++){
			String strKey = tkList.get(k);
			String strroundscale = roundingmap.get(strKey);
			int iroundscale = strroundscale==null||"".equals(strroundscale)?-1:Integer.parseInt(strroundscale);
			boolean isSumKey = SettlementOp.inArray(strSumkey, strKey, true);
			double dbValue = 0;
			if(isSumKey){
				dbValue = SettlementOp.getSumValue(strKey, targetList, iroundscale==-1?2:iroundscale);
			}else{
				dbValue = SettlementOp.getWeightedValue(getMAP_KEY_WEIGHT(), strKey, targetList, getRoundModeWithKey(strKey), iroundscale==-1?10:iroundscale);
			}
			String strEval = evalMap.get(strKey);
			if(strEval != null){
				strEval = strEval.replaceAll(strKey, String.valueOf(dbValue));
				dbValue = Calculator.getCalculatorValue(strEval);
			}
			resultMap.put(strKey, String.valueOf(dbValue));
		}
		return resultMap;
	}
	
	
	public String getSUFFIX_TARGET(){			//结算指标后缀
		return propsmap.get("SUFFIX_TARGET");
	}
	
	
	public String getSUMMARYTYPE(){					//需要在结算后进行汇总计算的pricetype 
		return propsmap.get("SUMMARYTYPE");
	}
	
	
	/**
	 * 得到所有的结算相关指标
	 * @param balanceTemplate
	 * @return
	 */
	private List<String> getUsedTargetKeys(SettlementTemplate balanceTemplate, boolean hasQualitySuffix){
		List<String> keysList = new ArrayList<String>();
		String strSumKey = propsmap.get("SUMKEY");
		for(int i=0; i< balanceTemplate.getGroupList().size(); i++){
			Map<String,String> groupMap = balanceTemplate.getGroupList().get(i);
			String strRownum = groupMap.get(SettlementOp.TMP_GROUP_MAP_KEY_ROWNUM);
			String strQualityKey = groupMap.get(SettlementOp.TMP_GROUP_MAP_KEY_Quality);	//质量结算依据指标代码
			strQualityKey = propsmap.get(strQualityKey)==null?strQualityKey:propsmap.get(strQualityKey);
			String strQualitysuffix = strQualityKey;
			List<String> keysListTmp = getUsedTargetKeys4GroupRow(balanceTemplate, strRownum);
			Iterator<String> keysIterator = keysListTmp.iterator();
			while(keysIterator.hasNext()){
				String strKey = (String) keysIterator.next();
				if(!SettlementOp.inArray(strSumKey, strKey, true))
					strKey = strKey + (hasQualitySuffix?strQualitysuffix:"");
				keysList.add(strKey);
			}
			String strQuantityKey = groupMap.get(SettlementOp.TMP_GROUP_MAP_KEY_Quantity);
			keysList.addAll(SettlementOp.getConditionKeys(strQuantityKey==null|| "null".equalsIgnoreCase(strQuantityKey)?"":strQuantityKey));
//			keysList.add(strQuantityKey);
			String strQualityweightKey = groupMap.get(SettlementOp.TMP_GROUP_MAP_KEY_Weight);
			keysList.addAll(SettlementOp.getConditionKeys(strQualityweightKey==null|| "null".equalsIgnoreCase(strQualityweightKey)?"":strQualityweightKey));
//			keysList.add(strQualityweightKey);
//			keysList.addAll(keysListTmp);
		}
		keysList = new ArrayList<String>(new HashSet<String>(keysList));
		return keysList;
	}
	
	
	/**
	 * 得到对应的分组行号下所有的结算相关指标
	 * @param balanceTemplate
	 * @param strRownum
	 * @return
	 */
	private List<String> getUsedTargetKeys4GroupRow(SettlementTemplate balanceTemplate, String strRownum){
		List<String> keysList = new ArrayList<String>();
		Map<String,String> groupRowMap = SettlementOp.getGroupMap4Rownum(balanceTemplate.getGroupList(), strRownum);
		String strEval = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_EVAL);
		String strEval4Index = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_EVAL4INDEX);
		String strEval4Price = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_EVAL4PRICE);
		keysList.addAll(SettlementOp.getConditionKeys(strEval));
		keysList.addAll(SettlementOp.getConditionKeys(strEval4Index==null|| "null".equalsIgnoreCase(strEval4Index)?"":strEval4Index));
		keysList.addAll(SettlementOp.getConditionKeys(strEval4Price==null || "null".equalsIgnoreCase(strEval4Price)?"":strEval4Price));
		keysList.addAll(getPriceTermsKeys(balanceTemplate, strRownum));
		keysList = new ArrayList<String>(new HashSet<String>(keysList));
		return keysList;
	}
	
	/**
	 * 根据条件重构批
	 * @param sourcesList		源数据list
	 * @param balanceTemplate	结算模板
	 * @return
	 * @throws Exception		
	 */
	private List<Map<String,String>> refactoringBatch(List<Map<String,String>> sourcesList,SettlementTemplate balanceTemplate) throws Exception{
		List<Map<String,String>> resultList = new ArrayList<Map<String,String>>();
//		根据指定的条件进行分组
		String strGroupByKey = balanceTemplate.getParaMap().get(SettlementOp.TMP_PARA_MAP_KEY_REFACTORING);
		if(strGroupByKey != null && !"".equals(strGroupByKey)){
			List<String> classifylist = new ArrayList<String>();
			for(int i =0; i < sourcesList.size() ; i++){
				Map<String,String> batchMap = sourcesList.get(i);
				String strGroupByValue = (String)batchMap.get(strGroupByKey);
				classifylist.add(strGroupByValue);
			}
			classifylist = new ArrayList<String>(new HashSet<String>(classifylist));
			String strPriceType = propsmap.get("WeightKeyWithPriceType");
			if(strPriceType == null){
				throw new Exception("配置错误，进行按日加权批处理时，结算加权量对应的费用类型(priceType)未配置。"); 
			}
			String strWeightKey = getQualityWeightkey(balanceTemplate, strPriceType);
			if(strWeightKey == null){
				throw new Exception("参数错误，在结算计价方案中找不到<" + strPriceType + ">对应的质量加权数量。"); 
			}
			//得到所有需要进行统计计算的指标对应map中的key值
			List<String> keyList = getUsedTargetKeys(balanceTemplate, true);
			//循环分组结果
			Iterator<String> it = classifylist.iterator();
			while(it.hasNext()){
				String groupValue = (String) it.next();
				String eval = "'" + strGroupByKey + "'" + SettlementOp.SIGN_EQUAL + "'" + groupValue + "'";
				//根据分组条件做过滤 构造分组结果对应的明细的list
				List<Map<String,String>> tmplist = new ArrayList<Map<String,String>>();
				try {
					tmplist= ListTools.cloneListMap(ListTools.extract(eval, sourcesList));
				} catch (ScriptException e) {
					throw new Exception("分组公式解析错误。");
				}
				if(tmplist.isEmpty()){
					continue;
				}
				//将明细list中的某一个map 赋值给分组结果的map 记录分组条件至该map
				Map<String,String> groupMap = new HashMap<String,String>();
				groupMap.putAll(tmplist.get(0));
				groupMap.put(strGroupByKey, groupValue);
				//获得需要汇总而不是加权平均的指标代码
				String strSumKey = propsmap.get("SUMKEY");
				//根据分组、价格及增扣款的指标key计算分组结果对应的指标
				for(int i=0; i< keyList.size(); i++){
					String strKey = keyList.get(i);
					if(tmplist.get(0).get(strKey) == null || "".equals(tmplist.get(0).get(strKey))){
						continue;
					}
					String strroundscale = roundingmap.get(strKey);
					int iroundscale = strroundscale==null||"".equals(strroundscale)?-1:Integer.parseInt(strroundscale);
					boolean isSumKey = SettlementOp.inArray(strSumKey, strKey, true);
					double dbValue = 0;
					if(isSumKey){
						dbValue = SettlementOp.getSumValue(strKey, tmplist, iroundscale==-1?2:iroundscale);
					}else{
						dbValue = SettlementOp.getWeightedValue(strWeightKey, strKey, tmplist, getRoundModeWithKey(strKey), iroundscale==-1?10:iroundscale);
					}
					groupMap.put(strKey, String.valueOf(dbValue));
				}
				//返回分组后list 
				resultList.add(groupMap);
			}
		}else{
			resultList = sourcesList;
		}
		return resultList;
	}
	
	
	/**
	 * 解析分组中的条件表达式，将变量替换为实际值
	 * @param strEval
	 * @param sourcesList
	 * @return
	 * @throws Exception 
	 */
	private String resolveEval(String strEval, List<Map<String,String>> sourcesList) throws Exception{
		//得到streval中最后一个条件表达式得起始位置
		//因为{}都是成对的所以从后向前能够解析多层嵌套表达式
		int index = strEval.lastIndexOf("{");
		
		//截出变量strVar记录开始位置index_begin
		String strVar = "";
		
		int index_begin = index;
		while(--index_begin>=0){
			char c = strEval.charAt(index_begin);
			if(Character.isLetter(c) || c=='_'){
				strVar = c + strVar;
			}else{
				break;
			}
		}
		index_begin = index_begin+1;
		//截出变量对应表达式strEval记录结束位置index_end
		String strEval4Var = "";
		int index_end = index;
		while(++index_end<strEval.length()){
			char c = strEval.charAt(index_end);
			if(c == '}'){
				break;
			}else{
				strEval4Var += c;
			}
		}
		index_end = index_end+1;
		String strreplaceval = String.valueOf(SettlementOp.getSumValue(strVar, strEval4Var, sourcesList));
		String strneweval = strEval.substring(0, index_begin) + strreplaceval + strEval.substring(index_end, strEval.length());
		return strneweval;
	}
	
	
	/**
	 * 设置结算指标
	 * @param sourcesList
	 * @param qualityKeysList
	 * @param strQualitySuffix
	 * @throws Exception
	 */
	private void setQualityKeys(List<Map<String,String>> sourcesList, List<String> qualityKeysList, String strQualitySuffix) throws Exception{
		for(int i = 0; i< sourcesList.size(); i++){
			Map<String,String> sRowMap = sourcesList.get(i);
			for(int j = 0; j< qualityKeysList.size(); j++){
				String strKey = qualityKeysList.get(j);
				String strQualityValue = sRowMap.get(strKey);
				//判断如果质量指标已经存在则不进行处理
				if(strQualityValue!= null && !"".equals(strQualityValue)){
					continue;
				}
				String strValue = sRowMap.get(strKey+strQualitySuffix);
				if(strValue==null || strValue.equals("")){
					continue;
				}
				String strOrginalUnit = sRowMap.get(strKey+strQualitySuffix+"_dw");
				String strNewValue = changeValue4Unit(strKey, strValue, strOrginalUnit);
				if(strNewValue !=null){
					strValue = strNewValue;
				}
				sRowMap.put(strKey,strValue);
			}
		}
	}
	
	/**
	 * 根据系统的质量公式构建结算指标
	 * @param sourcesGroupList	数据源批次
	 * @param strMode			加权或单批次
	 * @param strEval4Quality	质量公式
	 * @param strWeightKey		质量加权权重
	 * @throws Exception
	 */
	private void setQualityKeysByEval(List<Map<String,String>> sourcesGroupList, String strMode, String strEval4Quality, String strWeightKey) throws Exception{
		if(strEval4Quality!=null && !"".equals(strEval4Quality.trim())){
			String[] arrEval = strEval4Quality.split(";");
			for(int ie=0; ie<arrEval.length; ie++){
				String[] arrEvalSign = arrEval[ie].split("=");
				if(arrEvalSign.length!=2){
					continue;
				}
				String strTargetKey = arrEvalSign[0];
				String strValueEval = arrEvalSign[1];
				List<String> keyslist = SettlementOp.getConditionKeys(strValueEval.toLowerCase());
				List<String> excludeKeysList = new ArrayList<String>();	//公式的key
				for(int i=0 ; i<Calculator.funcArray.length; i++){
					excludeKeysList.add(Calculator.funcArray[i]);
				}
				keyslist.removeAll(excludeKeysList);
				if(SettlementOp.PRICE_MODE_WEIGHTING.equals(strMode)){
					List<Map<String,String>> srclist = new ArrayList<Map<String,String>>();
//					构造该公式的对应指标list
					for(int irow =0; irow< sourcesGroupList.size(); irow++){
						Map<String,String> srcMap = sourcesGroupList.get(irow);
						Map<String,String> targetMap = new HashMap<String,String>();
						targetMap.put(strWeightKey, srcMap.get(strWeightKey));
						for(int ikey=0; ikey < keyslist.size(); ikey++){
							String strKey = keyslist.get(ikey);
							String strValue = srcMap.get(strKey);
							
							String strOrginalUnit = srcMap.get(strKey+"_dw");
							String strNewValue = changeValue4Unit(strKey, strValue, strOrginalUnit);
							if(strNewValue!= null){
								strValue = strNewValue;
							}
							targetMap.put(strKey,strValue);
						}
						srclist.add(targetMap);
					}
//					计算公式对应指标的加权值
					Map<String,String> targetMap = new HashMap<String,String>();
					for(int ikey=0; ikey < keyslist.size(); ikey++){
						String strKey = keyslist.get(ikey);
						String strroundscale = roundingmap.get(strKey);
						int iroundscale = strroundscale==null||"".equals(strroundscale)?-1:Integer.parseInt(strroundscale);
						double dbValue = SettlementOp.getWeightedValue(strWeightKey, strKey, srclist, getRoundModeWithKey(strKey), iroundscale, 0);
						targetMap.put(strKey, String.valueOf(dbValue));
					}
//					替换公式变量、计算公式值
					String strFormula = SettlementOp.replaceFormula(strValueEval, targetMap);
					double dbValue = Calculator.getCalculatorValue(strFormula);
//					将得到的结果循环写入每一批次
					for(int irow =0; irow< sourcesGroupList.size(); irow++){
						Map<String,String> srcMap = sourcesGroupList.get(irow);
						srcMap.put(strTargetKey, String.valueOf(dbValue));
					}
				}else{
					for(int irow =0; irow< sourcesGroupList.size(); irow++){
						Map<String,String> srcMap = sourcesGroupList.get(irow);
						Map<String,String> targetMap = new HashMap<String,String>();
						for(int ikey=0; ikey<keyslist.size(); ikey++){
							String strKey = keyslist.get(ikey);
							String strValue = srcMap.get(strKey);
							
							String strOrginalUnit = srcMap.get(strKey+"_dw");
							String strNewValue = changeValue4Unit(strKey, strValue, strOrginalUnit);
							if(strNewValue!= null){
								strValue = strNewValue;
							}
							targetMap.put(strKey,strValue);
						}
						String strFormula = SettlementOp.replaceFormula(strValueEval, targetMap);
						double dbValue = Calculator.getCalculatorValue(strFormula);
						srcMap.put(strTargetKey, String.valueOf(dbValue));
					}
				}
			}
		}
	}
	
	/**
	 * 设置结算批中的结算数量指标
	 * @param sourcesList		源批
	 * @param strQuantityKey		数量指标key
	 * @throws Exception
	 */
	private void setQuantityKey(List<Map<String,String>> sourcesList, String strKey, String strQuantityKey) throws Exception{
		for(int i = 0; i< sourcesList.size(); i++){
			Map<String,String> sRowMap = sourcesList.get(i);
			List<String> keysList = SettlementOp.getConditionKeys(strQuantityKey);	//得到结算量公式的keys
			String amount = String.valueOf(Calculator.getCalculatorValue(SettlementOp.replaceFormula(strQuantityKey, keysList, sRowMap))); //计算结算量公式
			sRowMap.put(strKey, amount);	//将结算量赋值在记录集Map里
		}
	}
	
	/**
	 * 默认结算
	 * @param sources			结算批数据
	 * @param balanceTemplate	结算方案
	 * @return
	 * @throws Exception
	 */
	public List<Map<String,String>> toBalance(List<Map<String,String>> sourcesList,SettlementTemplate balanceTemplate, String strSettlementType) throws Exception{
		if(strSettlementType == null || "".equals(strSettlementType)){
			throw new Exception("结算类型为空");
		}
		if(balanceTemplate.getParaMap()!=null){
			propsmap.putAll(balanceTemplate.getParaMap());
		}
		if(balanceTemplate.getRoundMap()!=null){
			roundingmap.putAll(balanceTemplate.getRoundMap());
		}
		if(balanceTemplate.getRoundModeMap()!=null){
			roundModemap4contract.putAll(balanceTemplate.getRoundModeMap());
		}
		SettlementResult sr = calculation(sourcesList, balanceTemplate);
		List<Map<String,String>> result = getResult4Batchs(sourcesList, sr.getDetails(), strSettlementType);
		return result;
	}
	
	private void validateGroupSet(Map<String,String> groupRowMap) throws Exception{
		String strRownum = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_ROWNUM);
		String strEval = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_EVAL);
		String strEvalIndex = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_EVAL4INDEX);
		String strMode = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_MODE);
		String strPriceType = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_PRICETYPE);	//费用类型
		String strQuantityKey = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_Quantity);	//数量结算依据指标代码
		//QuantityKey = propsmap.get(QuantityKey)==null?QuantityKey:propsmap.get(QuantityKey);
		String strQualityKey = (String)groupRowMap.get(SettlementOp.TMP_GROUP_MAP_KEY_Quality);	//质量结算依据指标代码
//		异常判断
		if(strQuantityKey==null || "".equals(strQuantityKey)){
			throw new Exception("结算方案模板分组不正确，数量结算依据指标代码为空。");
		}
		if(strQualityKey==null || "".equals(strQualityKey)){
			throw new Exception("结算方案模板分组不正确，质量结算依据指标代码为空。");
		}
		if(strPriceType==null || "".equals(strPriceType)){
			throw new Exception("结算方案模板分组不正确，费用类型为空。");
		}
		if(strPriceType.indexOf(",")!=-1){
			throw new Exception("结算方案模板分组不正确，费用类型为不能包含字符<,>。");
		}
		if(strMode==null || "".equals(strMode)){
			throw new Exception("结算方案模板分组不正确，结算模式为空。");
		}
		if(strRownum==null || "".equals(strRownum)){
			throw new Exception("结算方案模板分组不正确，分组行号为空。");
		}
		if((strEval==null || "".equals(strEval)) && (strEvalIndex==null || "".equals(strEvalIndex))){
			throw new Exception("结算方案模板分组不正确，分组表达式为空。");
		}
	}
	
	/**
	 * 按照批次统计各批次的计价单价，并将总价写入key值为strPriceType中
	 * @param strPriceType
	 * @param resultList
	 * @param sourcesList
	 * @return
	 * @throws Exception
	 */
	private List<String> writeBatchPrice(String strPriceType, List<Map<String,String>> resultList, List<Map<String,String>> sourcesList) throws Exception{
		List<String> resultkeysList = new ArrayList<String>();
		//将各种价格写入map，并根据费用项目形成合计价格
		for(int i=0; i< sourcesList.size(); i++){
			Map<String,String> sRowMap = sourcesList.get(i);
			String strKey = sRowMap.get(SettlementOp.TMP_TERMS_MAP_KEY_PRICECODE);
			resultkeysList.add(strKey);
			String strValue = sRowMap.get(strKey)==null?"0":sRowMap.get(strKey);
			String strOldVal = "0";
			String strSumPrice = "0";
			int intBatchIndex = Integer.parseInt(sRowMap.get(getMAP_KEY_BATCHCODE()))-1;
			if(resultList.get(intBatchIndex) == null){
				resultList.set(intBatchIndex, sRowMap);
			}else{
				strOldVal = resultList.get(intBatchIndex).get(strKey)==null?"0":resultList.get(intBatchIndex).get(strKey);
				strSumPrice = resultList.get(intBatchIndex).get(strPriceType)==null?"0":resultList.get(intBatchIndex).get(strPriceType);
				//根据计价类型确认写入批次的指标，需根据definition.properties配置
				String strTargets = propsmap.get(strKey);
				if(strTargets!=null && !"".equals(strTargets)){
					String[] arrTargets = strTargets.split(",");
					for(int j=0; j<arrTargets.length; j++){
						String strtarget = arrTargets[j];
						if(sRowMap.get(strtarget)!=null){
							String strvalue = sRowMap.get(strtarget);
							resultList.get(intBatchIndex).put(strtarget, strvalue);
							resultList.get(intBatchIndex).put(strtarget + getSUFFIX_TARGET(), sRowMap.get(strtarget + getSUFFIX_TARGET()));
						}
					}
				}
//				resultList.get(intBatchIndex).putAll(sRowMap);
				sRowMap = resultList.get(intBatchIndex);
			}
			
			sRowMap.put(strKey, String.valueOf(CustomMaths.add(Double.parseDouble(strValue), Double.parseDouble(strOldVal))));
			if(!strKey.equals(SettlementOp.DeductionPriceCode_Tonsofwater))
				sRowMap.put(strPriceType, String.valueOf(CustomMaths.add(Double.parseDouble(strValue), Double.parseDouble(strSumPrice))));
			
			
			resultList.set(intBatchIndex, sRowMap);
		}
		resultkeysList.add(strPriceType);
		resultkeysList = new ArrayList<String>(new HashSet<String>(resultkeysList));
		return resultkeysList;
	}
	
	/**
	 * 写入单批次数量增扣
	 * @param sourcesList
	 */
	private void writeBatchQuantity(List<Map<String,String>> sourcesList){
		for(int i=0; i< sourcesList.size() ; i++){
			Map<String,String> sourMap = sourcesList.get(i);
			String strDedQuantity = sourMap.get(SettlementOp.DeductionPriceCode_Tonsofwater);
			if(strDedQuantity != null && !"".equals(strDedQuantity)){
				String strQuantity  = sourMap.get(getMAP_KEY_AMOUNT());
				double dbQuantity = strQuantity==null||"".equals(strQuantity)?0.0:Double.parseDouble(strQuantity);
				double dbDedQuantity = strDedQuantity==null||"".equals(strDedQuantity)?0.0:Double.parseDouble(strDedQuantity);
				sourMap.put(getMAP_KEY_AMOUNT(), String.valueOf(CustomMaths.add(dbQuantity, dbDedQuantity)));
			}
		}
	}
	
	
	/**
	 * 写入单批次总金额
	 * @param resultList
	 */
	private void writeBatchsMoney(List<Map<String,String>> resultList, String strPriceKey){
		for(int i=0; i< resultList.size(); i++){
			Map<String,String> rRowMap = resultList.get(i);
			String strQuantity = rRowMap.get(getMAP_KEY_AMOUNT());
			String strPrice = rRowMap.get(strPriceKey);
//			double dbquantity = strquantity==null||"".equals(strquantity)?0:Double.parseDouble(strquantity);
//			double dbprice = strprice==null||"".equals(strprice)?0:Double.parseDouble(strprice);
			String strMoney = CustomMaths.mul(strQuantity, strPrice);
			rRowMap.put(getMAP_KEY_AMOUNT_MONEY(), strMoney);
		}
	}
	
	
	/**
	 * 将map中的价格及价格类型写入list
	 * @param sourcesList	源list
	 * @param priceMap		需写入的价格map
	 * @return
	 */
	private List<Map<String,String>> writePriceList(List<Map<String,String>> sourcesList, Map<String,String> priceMap){
		List<Map<String,String>> resultList = new ArrayList<Map<String,String>>();
		Iterator<Entry<String, String>> priceIterator = priceMap.entrySet().iterator();
		while(priceIterator.hasNext()){
			Entry<String, String> e = (Entry<String, String>)priceIterator.next();
			String strKey = e.getKey();
			String strValue = e.getValue();
			List<Map<String,String>> tmpList = ListTools.cloneListMap(sourcesList);
			for(int i=0; i< tmpList.size(); i++){
				Map<String,String> tRowMap = tmpList.get(i);
				tRowMap.put(SettlementOp.TMP_TERMS_MAP_KEY_PRICECODE, strKey);
				tRowMap.put(strKey, strValue);
			}
			resultList.addAll(tmpList);
		}
		return resultList;
	}
}
